package com.dkm.websocket;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketSession;

//配置websocket地址（端点）
@ServerEndpoint("/myWebSocket/{userno}")
@Component
public class MyWebSocket {

	//记录在线人数
	private static Integer onlineCount=0;
	
	//存储连接对象的集合
	//private static CopyOnWriteArrayList<MyWebSocket> webSocketSet=new CopyOnWriteArrayList<MyWebSocket>();
	private static ConcurrentHashMap<String, MyWebSocket> webSocketSet=new ConcurrentHashMap<String, MyWebSocket>();
	
	//用户id
	private String userno="";
	
	
	//当前用户
	private Session session;
	/**
	 * 在客服端的websocket时间和方法，
	 * 在服务端有相对应的注解来表示
	 * 
	 */
	
	//当建立连接时触发
	@OnOpen
	public void onOpen(@PathParam(value = "userno") String userno,Session session) {
		System.out.println("用户编号》"+userno+"加入");
		this.userno = userno;//接收到发送消息的人员编号
		this.session=session;
		//加入用户集合中
		webSocketSet.put(userno, this);
		//在线人数加1
		addOnlineCount();
		System.out.println("有连接加入！当前在线人数："+getOnlineCount());
	}
	
	/**
	 * 当收到客户端消息时触发
	 * @param session 可选的参数
	 * @param message 客户端发送过来的消息
	 */
	@OnMessage
	public void onMessage(Session session,String  message) {
		System.out.println("客服端发来消息："+message);
		//群发消息
		//遍历出当前连接的websocket对象
		if(3<2) {
	        //群发消息
			sendAll(message);
		}else {
            //给指定的人发消息
			sendToUser(message);
		}
	}
	/**
	 * 给指定的人发消息
	 * @param message
	 */
	public void sendToUser(String message) {
		String sendUserno=message.split("[|]")[1];//要发送给消息的人
		String sendMessage=message.split("[|]")[0];//消息内容
		String now = this.getNowTime();
		try {
			//判断推送给的用户是否在线
			if(webSocketSet.get(sendUserno)!=null) {
				webSocketSet.get(sendUserno).sendMessage(now + "用户" + userno + "发来消息：" + " <br/> " + sendMessage);
			
			}else {
				System.out.println("当前用户不在线");
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		};
	}
	
	/**
	 * 给所有人发消息（广播）
	 * @param message
	 */
	public void sendAll(String message) {
		String now=this.getNowTime();
		String sendMessage = message.split("[|]")[0];
		//遍历HashMap
		for (String key : webSocketSet.keySet()) {
			
			try {
				//判断接收用户是否是当前发消息的用户
				if(!userno.equals(key)) {
					webSocketSet.get(key).sendMessage(now + "用户" + userno + "发来消息：" + " <br/> " + sendMessage);
					System.out.println("key>"+key);
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
	}
	
	/**
	 * 当连接关闭时触发
	 */
	@OnClose
	public void onClose() {
		if(!"".equals(userno)) {
			//移除用户
			webSocketSet.remove(userno);
			//在线人数减1
			subOnlineCount();
			System.out.println("有一连接关闭，当前在线人数："+getOnlineCount());
		}
	}
	
	/**
	 * 发生异常时触发
	 * throwable异常（必须）
	 * @param throwable
	 */
	@OnError
	public void onError(Throwable throwable) {
		System.out.println("连接异常，已断开。。。");
		throwable.printStackTrace();
	}
	
	/**
	 * 这个方法与上面几个方法不一样。没有用注解，是根据自己需要添加的方法。
	 * 服务端向客服端发送消息
	 * @param message
	 * @throws IOException
	 */
	public void sendMessage(String message) throws IOException {
		//getBasicRemote()阻塞式   getAsyncRemote()非阻塞式
		this.session.getBasicRemote().sendText(message);
        //this.session.getAsyncRemote().sendText(message);
	}
	
    public static synchronized int getOnlineCount() {
        return onlineCount;
    }
	
	/**
	 * 在线人数加1
	 */
	public static synchronized void addOnlineCount() {
		MyWebSocket.onlineCount++;
	}
	/**
	 * 在线人数减1
	 */
	public static synchronized void subOnlineCount() {
		MyWebSocket.onlineCount--;
	}
	
	/**
	 * 获取当前时间
	 * @return
	 */
	private String getNowTime() {
		Date date=new Date();
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		
		return sdf.format(date);
	}
}
